home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch12 / Qtree.cls < prev    next >
Encoding:
Visual Basic class definition  |  1999-06-19  |  5.7 KB  |  202 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "QtreeNode"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = False
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15. ' A quadtree node.
  16.  
  17. ' If this is a leaf node, its Objects
  18. ' collection contains the objects to draw.
  19. '
  20. ' Otherwise the object's children contain other
  21. ' QtreeNode objects.
  22.  
  23. ' The maximum number of objects the node can hold.
  24. Private Const MAX_OBJECTS = 100
  25.  
  26. ' The bounds this quadtree node represents.
  27. Public xmin As Single
  28. Public ymin As Single
  29. Public xmid As Single
  30. Public ymid As Single
  31. Public xmax As Single
  32. Public ymax As Single
  33.  
  34. ' The objects, if this is a leaf node.
  35. Private Objects As Collection
  36.  
  37. ' The quadtree children otherwise.
  38. Public NWchild As QtreeNode
  39. Public NEchild As QtreeNode
  40. Public SWchild As QtreeNode
  41. Public SEchild As QtreeNode
  42. ' Set the Drawn properties of the objects.
  43. Public Sub SetDrawn(ByVal new_value As Boolean)
  44. Dim obj As Object
  45.  
  46.     If Objects Is Nothing Then
  47.         ' We are not a leaf. Make our children
  48.         ' set Drawn for their objects.
  49.         NWchild.SetDrawn new_value
  50.         NEchild.SetDrawn new_value
  51.         SWchild.SetDrawn new_value
  52.         SEchild.SetDrawn new_value
  53.     Else
  54.         ' We are a leaf. Set Drawn for our objects.
  55.         For Each obj In Objects
  56.             obj.Drawn = new_value
  57.         Next obj
  58.     End If
  59. End Sub
  60. ' Find an object that contains this point.
  61. Public Function ObjectAt(ByVal X As Single, ByVal Y As Single) As Object
  62. Dim obj As Object
  63.  
  64.     Set ObjectAt = Nothing
  65.  
  66.     ' Stop if we don't contain the point.
  67.     If X < xmin Or X > xmax Or _
  68.        Y < ymin Or Y > ymax _
  69.        Then Exit Function
  70.  
  71.     ' Find the object.
  72.     If Objects Is Nothing Then
  73.         ' This is not a leaf node.
  74.         ' Search our children.
  75.         If Y > ymid Then
  76.             If X < xmid Then
  77.                 ' Search the northwest child.
  78.                 Set ObjectAt = NWchild.ObjectAt(X, Y)
  79.             Else
  80.                 ' Search the northeast child.
  81.                 Set ObjectAt = NEchild.ObjectAt(X, Y)
  82.             End If
  83.         Else
  84.             If X < xmid Then
  85.                 ' Search the southwest child.
  86.                 Set ObjectAt = SWchild.ObjectAt(X, Y)
  87.             Else
  88.                 ' Search the southeast child.
  89.                 Set ObjectAt = SEchild.ObjectAt(X, Y)
  90.             End If
  91.         End If
  92.     Else
  93.         ' This is a leaf node.
  94.         ' Search the objects it contains.
  95.         For Each obj In Objects
  96.             If obj.IsAt(X, Y) Then
  97.                 Set ObjectAt = obj
  98.                 Exit Function
  99.             End If
  100.         Next obj
  101.     End If
  102. End Function
  103. ' Add an object to the Objects collection.
  104. '
  105. ' If this gives us too many objects, create
  106. ' child nodes and subdivide.
  107. Public Sub Add(obj As Object)
  108.     If Objects Is Nothing Then
  109.         ' We are not a leaf node. Put the
  110.         ' object in the appropriate child.
  111.         PlaceObject obj
  112.     Else
  113.         ' We are a leaf node. Add the object
  114.         ' to the Objects collection.
  115.         Objects.Add obj
  116.  
  117.         ' See if need to subdivide.
  118.         If Objects.Count > MAX_OBJECTS Then Divide
  119.     End If
  120. End Sub
  121.  
  122. ' Create the children and divide the object.
  123. Private Sub Divide()
  124. Dim obj As Object
  125.  
  126.     ' Create the children.
  127.     Set NWchild = New QtreeNode
  128.     NWchild.SetBounds xmin, xmid, ymid, ymax
  129.  
  130.     Set NEchild = New QtreeNode
  131.     NEchild.SetBounds xmid, xmax, ymid, ymax
  132.  
  133.     Set SWchild = New QtreeNode
  134.     SWchild.SetBounds xmin, xmid, ymin, ymid
  135.  
  136.     Set SEchild = New QtreeNode
  137.     SEchild.SetBounds xmid, xmax, ymin, ymid
  138.  
  139.     ' Move the objects into the proper children.
  140.     For Each obj In Objects
  141.         PlaceObject obj
  142.     Next obj
  143.  
  144.     ' Remove the Objects collection.
  145.     Set Objects = Nothing
  146. End Sub
  147. ' Set the bounds for this quadtree node.
  148. Public Sub SetBounds(ByVal x1 As Single, ByVal x2 As Single, ByVal y1 As Single, ByVal y2 As Single)
  149.     xmin = x1
  150.     ymin = y1
  151.     xmax = x2
  152.     ymax = y2
  153.     xmid = (xmin + xmax) / 2
  154.     ymid = (ymin + ymax) / 2
  155. End Sub
  156. ' Place this object in the proper child(ren).
  157. Private Sub PlaceObject(ByVal obj As Object)
  158. Dim x1 As Single
  159. Dim x2 As Single
  160. Dim y1 As Single
  161. Dim y2 As Single
  162.  
  163.     obj.Bound x1, y1, x2, y2
  164.     If y2 > ymid And x1 < xmid Then NWchild.Add obj
  165.     If y2 > ymid And x2 > xmid Then NEchild.Add obj
  166.     If y1 < ymid And x1 < xmid Then SWchild.Add obj
  167.     If y1 < ymid And x2 > xmid Then SEchild.Add obj
  168. End Sub
  169. ' Draw the objects in this node on a PictureBox.
  170. Public Sub Draw(ByVal pic As PictureBox, ByVal x1 As Single, ByVal y1 As Single, ByVal x2 As Single, ByVal y2 As Single)
  171. Dim obj As Object
  172.  
  173.     ' Stop if we don't intersect the region
  174.     ' we're trying to draw.
  175.     If x2 < xmin Or x1 > xmax Or _
  176.        y2 < ymin Or y1 > ymax _
  177.        Then Exit Sub
  178.  
  179.     ' Draw a red box around our display region.
  180.     pic.Line (xmin, ymin)-(xmax, ymax), vbRed, B
  181.  
  182.     ' Draw the objects.
  183.     If Objects Is Nothing Then
  184.         ' We are not a leaf. Make our children
  185.         ' draw themselves.
  186.         NWchild.Draw pic, x1, y1, x2, y2
  187.         NEchild.Draw pic, x1, y1, x2, y2
  188.         SWchild.Draw pic, x1, y1, x2, y2
  189.         SEchild.Draw pic, x1, y1, x2, y2
  190.     Else
  191.         ' We are a leaf. Make the objects
  192.         ' draw themselves.
  193.         For Each obj In Objects
  194.             obj.Draw pic
  195.         Next obj
  196.     End If
  197. End Sub
  198. ' Start with an empty Objects collection.
  199. Private Sub Class_Initialize()
  200.     Set Objects = New Collection
  201. End Sub
  202.